﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.Data;
using MySql.Data.MySqlClient;
using FetchDataSystem.DAL;

namespace FetchDataSystem
{
    public class ModBus
    {
        public static string ModBusRead(SerialPort com)
        {
            string dataInfo = null;
            try
            {
                //向从站发送请求包
                byte[] buffers = { 0x01, 0x03, 0x00, 0x00, 0x00, 0x0A, 0xC5, 0xCD };
                com.Write(buffers, 0, buffers.Length);
                /*
                 * 一个完整的RTU
                 * 01 03 14 00 1C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 74 F5
                 */
                byte[] readHead = null;//头部数组
                byte[] dataNum = null;//数据数量数组
                byte[] datas = null;//数据数组
                byte[] crc = null;//校验数组
                //读取头部（1,2字节)
                readHead = ReadBuff(com, 0, 2);
                //读取第三个字节
                dataNum = ReadBuff(com, 0, 1);
                //读取数据字节
                datas = ReadBuff(com, 0, dataNum[0]);
                //读取校验字节
                crc = ReadBuff(com, 0, 2);
                //将校验数组中的数据转换成uint数据
                uint getedCrc = BitConverter.ToUInt16(crc, 0);
                //合并前三个数组
                byte[] newArr = new byte[readHead.Length + dataNum.Length + datas.Length];
                readHead.CopyTo(newArr, 0);
                dataNum.CopyTo(newArr, readHead.Length);
                datas.CopyTo(newArr, readHead.Length + dataNum.Length);
                //crc校验
                uint crc16 = Crc16_Modbus(newArr, newArr.Length);
                //判断
                if (getedCrc == crc16)
                {
                    StringBuilder sb = new StringBuilder();
                    if (BitConverter.IsLittleEndian)
                    {
                        for (int i = 0; i < datas.Length; i += 2)
                        {
                            byte[] temps = { datas[i + 1], datas[i] };
                            sb.Append(BitConverter.ToUInt16(temps, 0));
                        }
                        dataInfo = sb.ToString();
                    }
                }

            }
            catch(Exception ex)
            {
                throw ex;
            }
            return dataInfo;
        }
        /// <summary>
        /// 读取串口中指定偏移量的数据
        /// </summary>
        /// <param name="com"></param>
        /// <param name="offSet"></param>
        /// <param name="len"></param>
        /// <returns></returns>
        private static byte[] ReadBuff(SerialPort com,int offSet,int len)
        {
            byte[] datas = new byte[len];
            int result = 0;
            //防止丢包(全部丢了，部分丢了)
            do
            {
                result = result + com.Read(datas, offSet+result, len-result);
            } while (result < len);
           
            return datas;
        }
        /// <summary>
        /// CRC16校验
        /// </summary>
        /// <param name="datas"></param>
        /// <param name="len"></param>
        /// <returns></returns>
        
        private static uint Crc16_Modbus(byte[] datas,int len)
        {
            uint i, j;
            uint crc16 = 0xffff;
            for (i = 0; i < len; i++)
            {
                crc16 ^= datas[i];
                for (j = 0; j < 8; j++)
                {
                    if ((crc16 & 0x01) == 1)
                    {
                        crc16 = (crc16 >> 1) ^ 0xA001;
                    }
                    else
                    {
                        crc16 = crc16 >> 1;
                    }
                }
            }
            return crc16;
        }

    }

    public class Session
    {
        public static string UserId;//登录Id
        public static string LoginName;//用户名
        public static string LoginPwd;//登录密码
    }
    /// <summary>
    /// 字典处理类
    /// </summary>
    public class DictHandle
    {
        /// <summary>
        /// 根据类型和值获得标签值
        /// </summary>
        /// <param name="type"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string GetDictLable(string type,string value)
        {
            string reslut = null;
            string sql = "select * from sys_dict where type=@type and value=@value";
            try
            {
                using (MySqlDataReader dr = DBHelper.ExecuteReader(DBHelper.ConnectionString, CommandType.Text, sql, new MySqlParameter[] {
                    new MySqlParameter("@type",type),
                    new MySqlParameter("@value",value)
                }
                    ))
                {
                    if (dr.Read())
                    {
                        reslut = dr["label"].ToString();
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return null;
            }
            return reslut;
        }
    }
    
}
